/* 
** Copyright (C) 2006  sejishikong <sejishikong@263.net>
** Authors:    sejishikong <sejishikong@263.net>
**             Wei Lian <lianwei3@gmail.com> 
** Maintainer: Wei Lian
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License Version 2 as
**    published by the Free Software Foundation;
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
*/

#include "sys.h"
#include <netdb.h>

#ifdef ALSA
Sys::Sys (QObject * parent, const char *name):
QObject (parent, name)
{
   assert (snd_mixer_open (&mixer, 0) >= 0);
   snd_mixer_attach (mixer, "default");
   snd_mixer_selem_register (mixer, NULL, NULL);
   snd_mixer_load (mixer);

   ///alsa mixer init
   for (pcm_element = snd_mixer_first_elem (mixer);
	pcm_element; pcm_element = snd_mixer_elem_next (pcm_element))
      if (strcasecmp ("PCM", snd_mixer_selem_get_name (pcm_element)) == 0) {
	 long int a, b;
	 long alsa_min_vol, alsa_max_vol;
	 snd_mixer_selem_get_playback_volume (pcm_element,
					      SND_MIXER_SCHN_FRONT_LEFT, &a);
	 snd_mixer_selem_get_playback_volume (pcm_element,
					      SND_MIXER_SCHN_FRONT_RIGHT, &b);

	 snd_mixer_selem_get_playback_volume_range (pcm_element,
						    &alsa_min_vol,
						    &alsa_max_vol);
	 snd_mixer_selem_set_playback_volume_range (pcm_element, 0, 100);
	 break;
      }
}

Sys::~Sys ()
{
   snd_mixer_close (mixer);
}

int
Sys::sound_read ()
{
   long ll, lr;
   snd_mixer_handle_events (mixer);
   snd_mixer_selem_get_playback_volume (pcm_element,
					SND_MIXER_SCHN_FRONT_LEFT, &ll);
   snd_mixer_selem_get_playback_volume (pcm_element,
					SND_MIXER_SCHN_FRONT_RIGHT, &lr);
   return (ll + lr) >> 1;
}

void
Sys::sound_write (int leftright)
{
   snd_mixer_selem_set_playback_volume (pcm_element,
					SND_MIXER_SCHN_FRONT_LEFT, leftright);
   snd_mixer_selem_set_playback_volume (pcm_element,
					SND_MIXER_SCHN_FRONT_RIGHT,
					leftright);
}

#else

Sys::Sys (QObject * parent, const char *name):
QObject (parent, name)
{
   if ((sound_handle = open ("/dev/mixer", O_RDWR, 0)) == -1) {
      ::perror ("/dev/mixer");
   }
}

Sys::~Sys ()
{
   ::close (sound_handle);
}

int
Sys::sound_read ()
{
   int result;
   if (::ioctl (sound_handle, MIXER_READ (4), &result) == -1) {
      ::perror ("read_error");
      return -1;
   }
   result = ((result >> 8) + (result & 0xFF)) >> 1;
   result = (result > 0) ? result : 0;
   result = (result < 100) ? result : 100;
   return result;
}

void
Sys::sound_write (int leftright)
{
   leftright = (leftright < 0) ? 0 : leftright;
   leftright = (leftright > 100) ? 100 : leftright;
   leftright = (leftright << 8) | (leftright & 0xFF);
   if (::ioctl (sound_handle, MIXER_WRITE (4), &leftright) == -1) {
      perror ("write_error");
      return;
   }
}

#endif


int
Sys::connect_to_server (char *host, int portnum)
{
   int sock;
   struct sockaddr_in serv_addr;
   struct hostent *server;

   sock =::socket (AF_INET, SOCK_STREAM, 0);
   if (sock == -1) {
      perror ("ERROR opening socket");
      return -3;
   }
   server =::gethostbyname (host);
   if (server == NULL) {
      perror ("ERROR, no such host");
      close (sock);
      return -2;
   }
   ::memset ((char *) &serv_addr, 0, sizeof (serv_addr));
   serv_addr.sin_family = AF_INET;
   ::memcpy ((char *) &serv_addr.sin_addr.s_addr,
	     (char *) server->h_addr, server->h_length);
   serv_addr.sin_port = htons (portnum);

//  int flags = fcntl (sock, F_GETFL, 0);
//  fcntl (sock, F_SETFL, flags | O_NONBLOCK);
   if (::connect
       (sock, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) == -1) {
      ::close (sock);
      return -1;
   }
   return sock;
}
